package cn.hsa.fqz.task.service.impl;

import cn.hsa.fqz.common.enums.FileType;
import cn.hsa.fqz.common.utils.snowflake.IdUtil;
import cn.hsa.fqz.ftp.FtpConfig;
import cn.hsa.fqz.ftp.FtpUploader;
import cn.hsa.fqz.task.dao.TSysFileAccessoryMapper;
import cn.hsa.fqz.task.entity.TSysFileAccessoryDO;
import cn.hsa.fqz.task.entity.TSysFileDO;
import cn.hsa.fqz.task.service.TSysFileAccessoryService;
import cn.hsa.fqz.task.service.TSysFileService;
import cn.hsa.fqz.task.service.dto.LoginUserDTO;
import cn.hsa.hsaf.core.fsstore.FSAccessControlList;
import cn.hsa.hsaf.core.fsstore.FSEntity;
import cn.hsa.hsaf.core.fsstore.FSManager;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.compress.utils.Lists;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author luoze
 */
@Slf4j
@Service
public class TSysFileAccessoryServiceImpl
        extends ServiceImpl<TSysFileAccessoryMapper, TSysFileAccessoryDO>
        implements TSysFileAccessoryService {

    @Autowired
    private TSysFileService fileService;

    @Resource(name = "dfsManager")
    private FSManager fsManager;

    @Value("${fsstore.bucket}")
    private String bucket;

    @Value("${zmjk.ftp.host}")
    private String ftpHost;

    @Value("${zmjk.ftp.port}")
    private Integer ftpPort;

    @Value("${zmjk.ftp.uname}")
    private String ftpUname;

    @Value("${zmjk.ftp.pwd}")
    private String ftpPwd;

    @Value("${zmjk.ftp.url}")
    private String ftpUrl;

    @Value("{zmjk.ftp.rootdir}")
    private String rootDir;

    @Override
    public Boolean add(String accessoryId, Integer type, String fileNo) {
        TSysFileAccessoryDO accessory = new TSysFileAccessoryDO();
        accessory.setAccessoryId(accessoryId);
        accessory.setFileNo(fileNo);
        accessory.setType(type);

       return this.save(accessory);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String upload(String accessoryId, FileType fileType,LoginUserDTO dto, MultipartFile file) {

        String keyId = bucket + accessoryId + "-" + IdUtil.INSTANCE.get();

        FSEntity fsEntity = new FSEntity();
        fsEntity.setAcl(FSAccessControlList.Default);
        fsEntity.setContentType(file.getContentType());
        fsEntity.setKeyId(keyId);
        fsEntity.setName(file.getOriginalFilename());
        fsEntity.setUpdatedate(new Date());
        try {
            fsEntity.setInputstream(file.getInputStream());
            fsEntity.setSize(file.getInputStream().available());
        } catch (IOException e) {
            log.error("文件流异常={}", e.getMessage(), e);
            return "";
        }
        fsManager.putObject(bucket, fsEntity);

        TSysFileDO fileDO = new TSysFileDO();
        fileDO.setFileDir(bucket);
        fileDO.setFileName(file.getOriginalFilename());
        fileDO.setFileSize(file.getSize());
        fileDO.setUploader(dto.getUid());
        fileDO.setUploadTime(new Date());
        fileDO.setFileNo(keyId);
        fileService.save(fileDO);

        if(Strings.isBlank(accessoryId)){
            TSysFileAccessoryDO accessory = new TSysFileAccessoryDO();
            accessory.setAccessoryId(accessoryId);
            accessory.setFileNo(keyId);
            accessory.setType(fileType.getValue());

            this.save(accessory);
        }
        return keyId;
    }

    @Override
    public String upload(String directory,String subDirectory,FileType fileType, LoginUserDTO dto, MultipartFile file){
        String remotePath = rootDir+File.separator+directory+File.separator+subDirectory;
        File folder = new File(remotePath);
        String fileUrl = "";
        if(!folder.isDirectory()){
            folder.mkdirs();
            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            try{
                file.transferTo(new File(folder, newName));
                fileUrl = ftpUrl+FtpUploader.SEPRATOR+directory+FtpUploader.SEPRATOR+subDirectory+FtpUploader.SEPRATOR+file.getOriginalFilename();
            }catch(Exception e){
                log.error("文件流异常={}", e.getMessage(), e);
                return "";
            }
        }
        return fileUrl;
    }

    @Override
    public String uploadFtp(String directory,String subDirectory,FileType fileType, LoginUserDTO dto, MultipartFile file) throws Exception {

        FtpConfig config = new FtpConfig(ftpHost,ftpPort==null?21:ftpPort,ftpUname,ftpPwd);
        FtpUploader uploader = new FtpUploader(config);
        String remoteFileName = directory+File.separator+subDirectory+File.separator+file.getOriginalFilename();
        boolean flag = uploader.uploadFile(file.getInputStream(),directory,file.getOriginalFilename());
        if(flag){
            TSysFileDO fileDO = new TSysFileDO();
            fileDO.setFileDir(fileType.getBucket());
            fileDO.setFileName(file.getOriginalFilename());
            fileDO.setFileSize(file.getSize());
            fileDO.setUploader(dto.getUid());
            fileDO.setUploadTime(new Date());
            fileDO.setFileNo(Md5Crypt.apr1Crypt(remoteFileName));
            fileService.save(fileDO);
            return ftpUrl+FtpUploader.SEPRATOR+directory+FtpUploader.SEPRATOR+subDirectory+FtpUploader.SEPRATOR+file.getOriginalFilename();
        }else{
            return "";
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(String accessoryId, FileType fileType, String fileNo) {

        LambdaQueryWrapper<TSysFileAccessoryDO>
                wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TSysFileAccessoryDO::getFileNo, fileNo);
        wrapper.eq(TSysFileAccessoryDO::getType, fileType.getValue());

        fsManager.deleteObject(bucket, fileNo);

        LambdaQueryWrapper<TSysFileDO>
                wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(TSysFileDO::getFileNo, fileNo);

        fileService.remove(wrapper1);
        return this.remove(wrapper);
    }


    @Override
    public FSEntity get(String accessoryId, FileType fileType, String fileNo) {
        return fsManager.getObject(bucket, fileNo);
    }

    @Override
    public List<TSysFileDO> list(String accessoryId, FileType fileType) {
        LambdaQueryWrapper<TSysFileAccessoryDO>
                wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TSysFileAccessoryDO::getAccessoryId, accessoryId);
        wrapper.eq(TSysFileAccessoryDO::getType, fileType.getValue());

        List<TSysFileAccessoryDO> fileAccessoryDOS = this.list(wrapper);

        List<String> fileNos = fileAccessoryDOS.stream().map(TSysFileAccessoryDO::getFileNo).collect(Collectors.toList());

        if(CollectionUtil.isEmpty(fileNos)){
            return Lists.newArrayList();
        }else{
            LambdaQueryWrapper<TSysFileDO>
                    wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.in(TSysFileDO::getFileNo, fileNos);

            return fileService.list(wrapper1);
        }
    }
}




